#include "stdafx.h"
#include "object/GameObject.h"
#include "object/Camera.h"
#include "Stage.h"
#include "config/EngineCon.h"
#include "Display.h"

using namespace unigame;

Stage* Stage::s_instance = 0;
int32u Stage::s_flag = 0;

Stage::~Stage()
{
	clearStage(); 
	for(int32u i = 0, size = m_displays.size(); i < size; ++i)
	{
		delete m_displays[i];
	}
	m_displays.clear();
}

void Stage::init()
{
	addDisplay();
}

void Stage::clearStage()
{
	for(int32u i = 0, size = m_gameObjectList.size(); i < size; ++i)
	{
		m_gameObjectList[i]->release();
	}
	m_gameObjectList.clear();
	m_cameraList.clear();
}

void Stage::addToStage(GameObject *obj)
{
	if(obj == 0)
	{
		return;
	}
	obj->removeFromFather();
	m_gameObjectList.push_back(obj);
	obj->retain();
	if(obj->type() == E_CAMERA_GOT)
	{
		Camera* cam = (Camera*)obj;
		m_cameraList.push_back(cam);
		cam->display(DEFAULT_DISPLAY_ID);
	}
}

void Stage::removeFromStage(int32u index)
{
	assert(index >= 0 && index < (int32u)m_gameObjectList.size());
	std::vector<GameObject*>::iterator it = m_gameObjectList.begin() + index;
	it = m_gameObjectList.erase(it);
	(*it)->removeFromFather();
	(*it)->release();
	if((*it)->type() == E_CAMERA_GOT)
	{
		removeCamera(*it);
	}
}

void Stage::removeFromStage(GameObject *obj)
{
	for(std::vector<GameObject*>::iterator it = m_gameObjectList.begin(), end = m_gameObjectList.end();
		it < end; ++it)
	{
		if(obj == (*it))
		{
			obj->removeFromFather();
			m_gameObjectList.erase(it);
			obj->release();
			if(obj->type() == E_CAMERA_GOT)
			{
				removeCamera(obj);
			}
			return;
		}
	}
}

void Stage::removeCamera(GameObject* obj)
{
	for(std::vector<Camera*>::iterator it = m_cameraList.begin(); it < m_cameraList.end(); ++it)
	{
		if((*it) == obj)
		{
			m_cameraList.erase(it);
			return;
		}
	}
}

int32u Stage::addDisplay()
{
	int32u size = m_displays.size();
	int32u res = DEFAULT_DISPLAY_ID;
	if(size == 0)
	{
		m_displays.push_back(uni_new Display(DEFAULT_DISPLAY_ID));
	}
	else
	{
		res = m_displays[size - 1]->getID() + 1;
		m_displays.push_back(uni_new Display(res));
	}
	return res;
}

Display* Stage::getDisplay(int32u disID)
{
	for(int32u i = 0, size = m_displays.size(); i < size; ++i)
	{
		if(disID == m_displays[i]->getID())
		{
			return m_displays[i];
		}
	}
	return 0;
}

void Stage::onResizeScreen()
{
	for(int32u i = 0, size = m_displays.size(); i < size; ++i)
	{
		m_displays[i]->resize();
	}
}

void Stage::removeDisplay(int32u disID)
{
	for(std::vector<Display*>::iterator it = m_displays.begin(); it < m_displays.end(); ++it)
	{
		if((*it)->getID() == disID)
		{
			delete (*it);
			m_displays.erase(it);
			return;
		}
	}
}

GameObject* Stage::isInStage(GameObject* go)
{
	while(go->father())
	{
		go = go->father();
	}
	for(int32u i = 0, size = m_gameObjectList.size(); i < size; ++i)
	{
		if(m_gameObjectList[i] == go)
		{
			return go;
		}
	}
	return 0;
}

void Stage::update()
{
	for(int32u i = 0, size = m_gameObjectList.size(); i < size; ++i)
	{
		GameObject* go = m_gameObjectList[i];
		while(go)
		{
			if(go->isEnable())
			{
				go->update();
				go = go->next();
			}
			else
			{
				go->next(true);
			}
		}
	}
	if(getFlag(E_RENDER_LIST_CHANGE_SF))
	{
		for(int32u i = 0, size = m_cameraList.size(); i < size; ++i)
		{
			if(m_cameraList[i]->isEnable() && m_cameraList[i]->display())
			{
				m_cameraList[i]->cullObjects();
			}
		}
	}
	for(int32u i = 0, size = m_displays.size(); i < size; ++i)
	{
		m_displays[i]->update();
	}
	s_flag = 0;
}

void Stage::render()
{
	for(int32u i = 0, size = m_displays.size(); i < size; ++i)
	{
		m_displays[i]->viewPort();
		for(int32u j = 0, sizeJ = m_cameraList.size(); j < sizeJ; ++j)
		{
			if(m_displays[i] == m_cameraList[j]->display())
			{
				m_cameraList[j]->render();
			}
		}
	}
}